using System;
using System.Collections.Generic;
using Lab3.Entities;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Lab3
{
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        private List<Entity> _entities;

        private Camera _camera;

        private Jeep _jeep;
        private SnowPlow _snowPlow;
        private Skybox _skybox;
        private Reflectionsphere _reflectionsphere;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // *** Entitylist ***
            _entities = new List<Entity>();

            // *** Camera *** 
            _camera = new Camera(GraphicsDevice.Viewport, Vector3.Zero, Vector3.Up);
            
            // *** Objects ***
            // Skybox
            _skybox = new Skybox(_camera, Content.Load<Effect>("Effects/skybox"), Content.Load<TextureCube>("Models/Textures/Sunset"), GraphicsDevice);
            _skybox.Model = Content.Load<Model>("Models/cube");
            _entities.Add(_skybox);

            // Reflectionsphere
            _reflectionsphere = new Reflectionsphere(_camera, GraphicsDevice, Content.Load<Effect>("Effects/NormalBump"), Content.Load<Texture2D>("Models/Textures/water-normal-map"));
            _reflectionsphere.Model = Content.Load<Model>("Models/sphere_mapped");
            _reflectionsphere.Position = Vector3.Zero;
            
            // 1. Jeep
            _jeep = new Jeep(_camera, new BasicEffect(GraphicsDevice));
            _jeep.Model = Content.Load<Model>("Models/jeep");
            _jeep.Texture = Content.Load<Texture2D>("Models/Textures/jeep-1");
            _jeep.Position = new Vector3(0, 0, -5);
            _entities.Add(_jeep);

            // 2. Snowplow
            _snowPlow = new SnowPlow(_camera, new BasicEffect(GraphicsDevice), GraphicsDevice);
            _snowPlow.Model = Content.Load<Model>("Models/snowplow");
            _snowPlow.Position = new Vector3(0, 0, 5);
            _entities.Add(_snowPlow);

            // 3. Snowplow
            _snowPlow = new SnowPlow(_camera, new BasicEffect(GraphicsDevice), GraphicsDevice);
            _snowPlow.Model = Content.Load<Model>("Models/snowplow");
            _snowPlow.Position = new Vector3(0, 0, 10);
            _entities.Add(_snowPlow);

            // 4. Snowplow
            _snowPlow = new SnowPlow(_camera, new BasicEffect(GraphicsDevice), GraphicsDevice);
            _snowPlow.Model = Content.Load<Model>("Models/snowplow");
            _snowPlow.Position = new Vector3(0, 0, 15);
            _entities.Add(_snowPlow);

            // 5. Snowplow
            _snowPlow = new SnowPlow(_camera, new BasicEffect(GraphicsDevice), GraphicsDevice);
            _snowPlow.Model = Content.Load<Model>("Models/snowplow");
            _snowPlow.Position = new Vector3(-5, 0, 15);
            _snowPlow.Rotation = Matrix.CreateRotationY(3);
            _entities.Add(_snowPlow);

            // 6. Snowplow
            _snowPlow = new SnowPlow(_camera, new BasicEffect(GraphicsDevice), GraphicsDevice);
            _snowPlow.Model = Content.Load<Model>("Models/snowplow");
            _snowPlow.Position = new Vector3(-5, 0, 10);
            _snowPlow.Rotation = Matrix.CreateRotationY(3);
            _entities.Add(_snowPlow);

            // 7. Snowplow
            _snowPlow = new SnowPlow(_camera, new BasicEffect(GraphicsDevice), GraphicsDevice);
            _snowPlow.Model = Content.Load<Model>("Models/snowplow");
            _snowPlow.Position = new Vector3(-5, 0, 5);
            _snowPlow.Rotation = Matrix.CreateRotationY(3);
            _entities.Add(_snowPlow);


           
        }

        protected override void UnloadContent()
        {
        }

        protected override void Update(GameTime gameTime)
        {
            _camera.Update(gameTime);

            foreach (Entity entity in _entities)
            {
                entity.Update(gameTime);
            }

            _reflectionsphere.Update(gameTime);

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            // Reflectionsphere
            Matrix originalCameraView = _camera.View;
            Matrix originalCameraProjection = _camera.Projection;
            foreach (CubeMapFace mapFace in Enum.GetValues(typeof (CubeMapFace)))
            {
                _reflectionsphere.CreateCubeMap(mapFace);
                foreach (Entity entity in _entities)
                {
                    entity.Draw(GraphicsConstants.NormalDraw);
                }
                foreach (Entity entity in _entities)
                {
                    entity.Draw(GraphicsConstants.AlphaDraw);
                }
                _reflectionsphere.EndCubeMap();
            }
            _camera.View = originalCameraView;
            _camera.Projection = originalCameraProjection;

            // *** Draw objects ***
            // Sphere
            _reflectionsphere.Draw(GraphicsConstants.NormalDraw);

            // Normal
            foreach (Entity entity in _entities)
            {
                entity.Draw(GraphicsConstants.NormalDraw);
            }
            // Translucent
            foreach (Entity entity in _entities)
            {
                entity.Draw(GraphicsConstants.AlphaDraw);
            }
            base.Draw(gameTime);
        }
    }
}
